package com.thinvent.remotepassword.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.thinvent.remotepassword.dto.DeployDetail;
import com.thinvent.remotepassword.dto.RebotParam;
import com.thinvent.remotepassword.dto.RebotResponse;
import com.thinvent.remotepassword.entity.WikiDocData;
import com.thinvent.remotepassword.entity.WikiQaLog;
import com.thinvent.remotepassword.mapper.WikiDocDataMapper;
import com.thinvent.remotepassword.mapper.WikiQaLogMapper;
import com.thinvent.remotepassword.mapper.WikiRebotMapper;
import com.thinvent.remotepassword.entity.WikiRebot;
import com.thinvent.remotepassword.service.WikiRebotService;
import com.thinvent.remotepassword.util.GLMUtil;
import com.thinvent.remotepassword.util.SimilarityUtil;
import com.thinvent.remotepassword.util.TokenContext;
import com.thinvent.remotepassword.util.UserContext;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 知识库机器人管理表(WikiRebot)表服务实现类
 *
 * @author makejava
 * @since 2024-07-09 09:23:31
 */
@Service("wikiRebotService")
public class WikiRebotServiceImpl extends ServiceImpl<WikiRebotMapper, WikiRebot> implements WikiRebotService {

    @Resource
    private WikiRebotMapper wikiRebotMapper;

    @Resource
    private WikiDocDataMapper wikiDocDataMapper;

    @Resource
    private WikiQaLogMapper wikiQaLogMapper;

    private String url = "http://192.168.2.88:8103/wikiRebot/rebotApi";

    @Override
    public DeployDetail deployDetail(String id) {
        DeployDetail deployDetail = new DeployDetail();
        deployDetail.setUrl(url);
        deployDetail.setMethod("POST请求");
        // 构建请求参数
        RebotParam rebotParam = new RebotParam();
        rebotParam.setId(id);
        rebotParam.setPrompt("请输入您需要咨询的问题");
        deployDetail.setParams(JSON.toJSONString(rebotParam));
        deployDetail.setToken(TokenContext.get());
        return deployDetail;
    }

    @Override
    public RebotResponse rebotApi(RebotParam rebotParam) throws IOException {
        // 获取机器人信息
        String id = rebotParam.getId();
        WikiRebot wikiRebot = wikiRebotMapper.selectById(id);

        // 查询对话日志表看是否需要展示人工服务信息
        // 获取当前时间并减去1分钟
        LocalDateTime currentTime = LocalDateTime.now();
        LocalDateTime fiveMinutesAgo = currentTime.minusMinutes(1);
        Timestamp timestampFiveMinutesAgo = Timestamp.valueOf(fiveMinutesAgo);

        QueryWrapper<WikiQaLog> wrapper = new QueryWrapper<>();
        wrapper.eq("rebot_id", rebotParam.getId());
        wrapper.eq("user_id", UserContext.get());
        wrapper.eq("question", rebotParam.getPrompt());
        wrapper.ge("create_time", timestampFiveMinutesAgo);
        List<WikiQaLog> wikiQaLogs = wikiQaLogMapper.selectList(wrapper);
        if(!CollectionUtils.isEmpty(wikiQaLogs)) {
            if(wikiQaLogs.size() >= 3) {
                RebotResponse rebotResponse = new RebotResponse();
                rebotResponse.setPrompt(rebotParam.getPrompt());
                rebotResponse.setResponse(wikiRebot.getManualReplyContent());
                return rebotResponse;
            }
        }

        Map<String, List<WikiDocData>> wikiDocDataMap = new HashMap<>();
        if(null != wikiRebot) {
            List<String> docIdList = wikiRebot.getDocIdList();
            // 根据文档id查询文档知识数据列表
            QueryWrapper<WikiDocData> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("doc_id", docIdList);
            List<WikiDocData> wikiDocDataList = wikiDocDataMapper.selectList(queryWrapper);
            if(CollectionUtil.isNotEmpty(wikiDocDataList)) {
                // 使用Java 8 Stream API进行分组
                wikiDocDataMap = wikiDocDataList.stream()
                        .collect(Collectors.groupingBy(WikiDocData::getDocId));
            }
        }
        // 问题和向量得分对应的map
        Map<Double, String> sortedMap = new HashMap<>();
        // 日志的map
        Map<Double, String> sortedMapLog = new HashMap<>();
        // 将用户输入的prompt转化为向量
        String promptVet = SimilarityUtil.getVet(rebotParam.getPrompt());
        for (Map.Entry<String, List<WikiDocData>> entry : wikiDocDataMap.entrySet()) {
            List<WikiDocData> valueList = entry.getValue(); // 获取值（List<WikiDocData>）

            for (WikiDocData data : valueList) {
                try {
                    // 对每个WikiDocData对象进行操作
                    String questionVet = data.getQuestion();
                    // 进行向量的比较
                    double[][] promptVetDouble = SimilarityUtil.strToDoubleArray(promptVet);
                    double[][] questionVetDouble = SimilarityUtil.strToDoubleArray(data.getQuestionVector());
                    double v = SimilarityUtil.cosineSimilarity(promptVetDouble, questionVetDouble);
                    sortedMapLog.put(v, questionVet);
                    if(v >= 0.6) {
                        sortedMap.put(v, questionVet);
                    }
//                    sortedMap.put(v, questionVet);
                } catch (Throwable throwable) {
                    System.out.println(JSON.toJSONString(data));
                }
            }
        }
        // 如果用户输入的问题在知识库匹配到了多个问题答案，则全部返回给大模型
//        if(sortedMap.size() >= 2) {
//            // 使用Java 8 Stream API遍历Map并获取所有values到一个List中
//            List<String> valuesList = sortedMap.values().stream()
//                    .collect(java.util.stream.Collectors.toList());
//            String join = StringUtils.join(valuesList, "、");
//            String pro = "你现在是我的私人小助手，用户输入的问题是:" +
//                    rebotParam.getPrompt() + "，知识库匹配到的知识为：" + join + "，请你提示用户应该再次提问的时候应该选择哪个匹配到的问题";
//            String modelResponse = GLMUtil.getModelResponse(pro);
//            System.out.println("pro:" + pro);
//            RebotResponse rebotResponse = new RebotResponse();
//            rebotResponse.setPrompt(rebotParam.getPrompt());
//            rebotResponse.setResponse(modelResponse);
//            return rebotResponse;
//        }
        System.out.println("日志map的输入 : " + JSON.toJSONString(sortedMapLog));
        // 找出最高的记录
        double maxScore = Double.MIN_VALUE;
        String maxRecord = "";

        for (Map.Entry<Double, String> entry : sortedMapLog.entrySet()) {
            if (entry.getKey() > maxScore) {
                maxScore = entry.getKey();
                maxRecord = entry.getValue();
            }
        }
        String result = maxScore + ":\"" + maxRecord + "\"";
        System.out.println("最高的记录是：" + result);
        // 如果没有匹配上
        if(CollectionUtil.isEmpty(sortedMap)) {
            // 如果在设置的阈值之下的 则直接开发给机器人回答
            String modelResponse = GLMUtil.getModelResponse("请你帮我回答以下这个问题:" + rebotParam.getPrompt());
            RebotResponse rebotResponse = new RebotResponse();
            rebotResponse.setPrompt(rebotParam.getPrompt());
//            rebotResponse.setResponse(StringUtils.isNotBlank(wikiRebot.getManualReplyContent()) ? wikiRebot.getManualReplyContent() : "您的问题超出客服机器人的知识范围，如果有需要可以联系人工客服");
            rebotResponse.setResponse(modelResponse);
            return rebotResponse;
        }
        Optional<Map.Entry<Double, String>> maxEntry = sortedMap.entrySet().stream()
                .max(Map.Entry.comparingByKey());

        final String[] maxValue = new String[10];

        maxEntry.ifPresent(entry -> {
            maxValue[0] = entry.getValue();
        });
        // 根据maxValue[0]（向量值去查询answer）
        QueryWrapper<WikiDocData> queryWrapperOne = new QueryWrapper<>();
        queryWrapperOne.eq("question", maxValue[0]);
        List<WikiDocData> wikiDocDatas = wikiDocDataMapper.selectList(queryWrapperOne);
        if(CollectionUtil.isNotEmpty(wikiDocDatas)) {
            // 获取answer 并请求模型提取文档内容
            String answer = wikiDocDatas.get(0).getAnswer();
            String promptWord = wikiRebot.getPromptWord();
            String newText = promptWord.replace("[x]", rebotParam.getPrompt()).replace("[y]", answer);
            System.out.println(newText);
            // 植入回答风格
            if("简单风格".equals(rebotParam.getStyle())) {
                newText += "回答问题风格为：简单风格";
            }
            if("严谨标准风格".equals(rebotParam.getStyle())) {
                newText += "回答问题风格为：严谨标准，更多采用原文内容";
            }
            if("自然风格".equals(rebotParam.getStyle())) {
                newText += "回答问题风格为：自然和口语化";
            }
            if("普通风格".equals(rebotParam.getStyle())) {
                newText += "";
            }
            System.out.println("newText : " + newText);
            String modelResponse = GLMUtil.getModelResponse(newText);

            RebotResponse rebotResponse = new RebotResponse();
            rebotResponse.setPrompt(rebotParam.getPrompt());
            rebotResponse.setResponse(modelResponse);
            // 记录对话日志
            WikiQaLog wikiQaLog = new WikiQaLog();
            wikiQaLog.setQuestion(rebotParam.getPrompt());
            wikiQaLog.setAnswer(modelResponse);
            wikiQaLog.setRebotId(rebotParam.getId());
            wikiQaLog.setUserId(UserContext.get());
            wikiQaLog.setStandardAnswer(answer);
            wikiQaLog.setMatchedQuestion(wikiDocDatas.get(0).getQuestion());
            wikiQaLog.setMatchScore(maxScore);
            Date utilDate = new Date();
            Timestamp timestampFromDate = new Timestamp(utilDate.getTime());
            wikiQaLog.setCreateTime(timestampFromDate);
            wikiQaLog.setUpdateTime(timestampFromDate);

            wikiQaLogMapper.insert(wikiQaLog);
            return rebotResponse;
        }
        return null;
    }

}

